package com.anrongtec.zcpt.widget;


import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.animation.PathInterpolatorCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;

import com.anrongtec.zcpt.R;



/**
 * 带进度条的下载控件，有七种状态
 * 
 */
@SuppressLint("NewApi")
public class DownloadProgressButton extends TextView {
	// progressbtn_radius float 按钮的圆角,单位为px，默认为按钮高度一半
	// progressbtn_backgroud_color color 按钮原始颜色
	// progressbtn_backgroud_second_color color 进度条的颜色
	// progressbtn_text_color color 文本原始颜色
	// progressbtn_text_covercolor color 进度条上文本颜色

	private Context mContext;

	// 背景画笔
	private Paint mBackgroundPaint;
	// 按钮文字画笔
	private volatile Paint mTextPaint;
	// 第一个点画笔
	private Paint mDot1Paint;
	// 第二个点画笔
	private Paint mDot2Paint;

	// 背景颜色
	private int mBackgroundColor;
	// 下载中后半部分后面背景颜色
	private int mBackgroundSecondColor;
	// 文字颜色
	private int mTextColor;
	// 覆盖后颜色
	private int mTextCoverColor;

	private float mProgress = -1;
	private float mToProgress;
	private int mMaxProgress;
	private int mMinProgress;
	private float mProgressPercent;

	private float mButtonRadius;

	// 两个点向右移动距离
	private float mDot1transX;
	private float mDot2transX;

	private RectF mBackgroundBounds;
	private LinearGradient mProgressBgGradient;
	private LinearGradient mProgressTextGradient;

	// 点运动动画
	private AnimatorSet mDotAnimationSet;
	// 下载平滑动画
	private ValueAnimator mProgressAnimation;

	// 记录当前文字
	private CharSequence mCurrentText;

	private int mState;

	public DownloadProgressButton(Context context) {
		this(context, null);

	}

	public DownloadProgressButton(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	@SuppressLint("NewApi")
	public DownloadProgressButton(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		if (!isInEditMode()) {
			mContext = context;
			initAttrs(context, attrs);
			init();
			setupAnimations();
		}
	}

	private void initAttrs(Context context, AttributeSet attrs) {

		TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DownloadProgressButton);
		mBackgroundColor = a.getColor(R.styleable.DownloadProgressButton_progressbtn_backgroud_color,
				Color.parseColor("#6699ff"));
		mBackgroundSecondColor = a.getColor(R.styleable.DownloadProgressButton_progressbtn_backgroud_second_color,
				Color.LTGRAY);
		mButtonRadius = a.getFloat(R.styleable.DownloadProgressButton_progressbtn_radius, getMeasuredHeight() / 2);
		mTextColor = a.getColor(R.styleable.DownloadProgressButton_progressbtn_text_color, mBackgroundColor);
		mTextCoverColor = a.getColor(R.styleable.DownloadProgressButton_progressbtn_text_covercolor, Color.WHITE);
		a.recycle();
	}

	private void init() {

		mMaxProgress = 100;
		mMinProgress = 0;
		mProgress = 0;

		// 设置背景画笔
		mBackgroundPaint = new Paint();
		mBackgroundPaint.setAntiAlias(true);
		mBackgroundPaint.setStyle(Paint.Style.FILL);

		// 设置文字画笔
		mTextPaint = new Paint();
		mTextPaint.setAntiAlias(true);
		mTextPaint.setTextSize(50f);
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			// 解决文字有时候画不出问题
			setLayerType(LAYER_TYPE_SOFTWARE, mTextPaint);
		}

		// 设置第一个点画笔
		mDot1Paint = new Paint();
		mDot1Paint.setAntiAlias(true);
		mDot1Paint.setTextSize(50f);

		// 设置第二个点画笔
		mDot2Paint = new Paint();
		mDot2Paint.setAntiAlias(true);
		mDot2Paint.setTextSize(50f);

		// 初始化状态设为NONE
		setState(NONE);

	}

	private void setupAnimations() {

		// 两个点向右移动动画
		ValueAnimator dotMoveAnimation = ValueAnimator.ofFloat(0, 20);
		TimeInterpolator pathInterpolator = PathInterpolatorCompat.create(0.11f, 0f, 0.12f, 1f);
		dotMoveAnimation.setInterpolator(pathInterpolator);
		dotMoveAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float transX = (float) animation.getAnimatedValue();
				mDot1transX = transX;
				mDot2transX = transX;
				invalidate();
			}
		});
		dotMoveAnimation.setDuration(1243);
		dotMoveAnimation.setRepeatMode(ValueAnimator.RESTART);
		dotMoveAnimation.setRepeatCount(ValueAnimator.INFINITE);

		// 两个点渐显渐隐动画
		final ValueAnimator dotAlphaAnim = ValueAnimator.ofInt(0, 1243).setDuration(1243);
		dotAlphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				int time = (int) dotAlphaAnim.getAnimatedValue();
				int dot1Alpha = calculateDot1AlphaByTime(time);
				int dot2Alpha = calculateDot2AlphaByTime(time);
				mDot1Paint.setColor(mTextCoverColor);
				mDot2Paint.setColor(mTextCoverColor);
				mDot1Paint.setAlpha(dot1Alpha);
				mDot2Paint.setAlpha(dot2Alpha);
			}

		});

		dotAlphaAnim.addListener(new Animator.AnimatorListener() {
			@Override
			public void onAnimationStart(Animator animation) {
				mDot1Paint.setAlpha(0);
				mDot2Paint.setAlpha(0);
			}

			@Override
			public void onAnimationEnd(Animator animation) {
			}

			@Override
			public void onAnimationCancel(Animator animation) {

			}

			@Override
			public void onAnimationRepeat(Animator animation) {

			}
		});
		dotAlphaAnim.setRepeatMode(ValueAnimator.RESTART);
		dotAlphaAnim.setRepeatCount(ValueAnimator.INFINITE);
		// 两个点的动画集合
		mDotAnimationSet = new AnimatorSet();
		mDotAnimationSet.playTogether(dotAlphaAnim, dotMoveAnimation);

		// ProgressBar的动画
		mProgressAnimation = ValueAnimator.ofFloat(0, 1).setDuration(500);
		mProgressAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float timepercent = (float) animation.getAnimatedValue();
				mProgress = ((mToProgress - mProgress) * timepercent + mProgress);
				invalidate();
			}
		});

	}

	// 第一个点透明度计算函数
	private int calculateDot2AlphaByTime(int time) {
		int alpha;
		if (0 <= time && time <= 83) {
			double DAlpha = 255.0 / 83.0 * time;
			alpha = (int) DAlpha;
		} else if (83 < time && time <= 1000) {
			alpha = 255;
		} else if (1000 < time && time <= 1083) {
			double DAlpha = -255.0 / 83.0 * (time - 1083);
			alpha = (int) DAlpha;
		} else if (1083 < time && time <= 1243) {
			alpha = 0;
		} else {
			alpha = 255;
		}
		return alpha;
	}

	// 第二个点透明度计算函数
	private int calculateDot1AlphaByTime(int time) {
		int alpha;
		if (0 <= time && time <= 160) {
			alpha = 0;
		} else if (160 < time && time <= 243) {
			double DAlpha = 255.0 / 83.0 * (time - 160);
			alpha = (int) DAlpha;
		} else if (243 < time && time <= 1160) {
			alpha = 255;
		} else if (1160 < time && time <= 1243) {
			double DAlpha = -255.0 / 83.0 * (time - 1243);
			alpha = (int) DAlpha;
		} else {
			alpha = 255;
		}
		return alpha;
	}

	@SuppressWarnings("unused")
	private ValueAnimator createDotAlphaAnimation(int i, Paint mDot1Paint, int i1, int i2, int i3) {

		return new ValueAnimator();
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (!isInEditMode()) {
			drawing(canvas);
		}
	}

	private void drawing(Canvas canvas) {
		drawBackground(canvas);
		drawTextAbove(canvas);
	}

	/**
	 * 绘制纯背景
	 *
	 * @param canvas
	 * @param backgroundColor
	 *            背景颜色
	 */
	private void drawOnlyBackground(Canvas canvas, int backgroundColor) {
		if (mBackgroundPaint.getShader() != null) {
			mBackgroundPaint.setShader(null);
		}
		mBackgroundPaint.setColor(backgroundColor);
		canvas.drawRoundRect(mBackgroundBounds, mButtonRadius, mButtonRadius, mBackgroundPaint);
	}

	private void drawBackground(Canvas canvas) {
		mBackgroundBounds = new RectF();
		if (mButtonRadius == 0) {
			mButtonRadius = getMeasuredHeight() / 2;
		}
		mBackgroundBounds.left = 2;
		mBackgroundBounds.top = 2;
		mBackgroundBounds.right = getMeasuredWidth() - 2;
		mBackgroundBounds.bottom = getMeasuredHeight() - 2;

		// color
		switch (mState) {
		// 当是默认、等待两张状态，背景颜色为原始颜色
		case WAITING:
		case NONE:
			drawOnlyBackground(canvas, mBackgroundColor);
			break;
		// 打开、完成状态，背景颜色为进度条充满的颜色
		case OPEN:
		case FINISH:
			drawOnlyBackground(canvas, mBackgroundSecondColor);
			break;
		// 错误状态，背景颜色为红色
		case ERROR:
			mProgress = 0;
			drawOnlyBackground(canvas, Color.RED);
			break;
		// 下载中、等待状态，背景颜色渐变
		case DOWNLOADING:
		case PAUSE:
			mProgressPercent = mProgress / (mMaxProgress + 0f);
			mProgressBgGradient = new LinearGradient(0, 0, getMeasuredWidth(), 0,
					new int[] { mBackgroundSecondColor, mBackgroundColor },
					new float[] { mProgressPercent, mProgressPercent + 0.001f }, Shader.TileMode.CLAMP);
			mBackgroundPaint.setColor(mBackgroundSecondColor);
			mBackgroundPaint.setShader(mProgressBgGradient);
			canvas.drawRoundRect(mBackgroundBounds, mButtonRadius, mButtonRadius, mBackgroundPaint);
			break;
		}
	}

	/**
	 * 绘制纯文本
	 *
	 * @param canvas
	 * @param text
	 *            文本
	 * @param textColor
	 *            文本颜色
	 * @param y
	 *            文本坐标
	 */
	private void drawOnlyText(Canvas canvas, String text, int textColor, float y) {
		float textWidth = mTextPaint.measureText(text.toString());

		mTextPaint.setShader(null);
		mTextPaint.setColor(textColor);
		canvas.drawText(text.toString(), (getMeasuredWidth() - textWidth) / 2, y, mTextPaint);
	}

	/**
	 * 绘制带点的文本
	 *
	 * @param canvas
	 * @param text
	 *            文本
	 * @param textColor
	 *            文本颜色
	 * @param y
	 *            文本坐标
	 */
	private void drawDotText(Canvas canvas, String text, int textColor, float y) {
		float textWidth = mTextPaint.measureText(text.toString());
		mTextPaint.setColor(textColor);
		mDot1Paint.setColor(textColor);
		mDot2Paint.setColor(textColor);
		canvas.drawText(text.toString(), (getMeasuredWidth() - textWidth) / 2, y, mTextPaint);
		canvas.drawCircle((getMeasuredWidth() + textWidth) / 2 + 4 + mDot1transX, y, 4, mDot1Paint);
		canvas.drawCircle((getMeasuredWidth() + textWidth) / 2 + 24 + mDot2transX, y, 4, mDot2Paint);
	}

	/**
	 * 绘制带进度的渐变文本
	 *
	 * @param canvas
	 * @param text
	 *            文本
	 * @param textColor
	 *            文本颜色
	 * @param textCoverColor
	 *            被进度覆盖的文本颜色
	 * @param y
	 *            文本坐标
	 */
	private void drawProgressText(Canvas canvas, String text, int textColor, int textCoverColor, float y) {
		float textWidth = mTextPaint.measureText(text.toString());
		// 进度条压过距离
		float coverlength = getMeasuredWidth() * mProgressPercent;
		// 开始渐变指示器
		float indicator1 = getMeasuredWidth() / 2 - textWidth / 2;
		// 结束渐变指示器
		float indicator2 = getMeasuredWidth() / 2 + textWidth / 2;
		// 文字变色部分的距离
		float coverTextLength = textWidth / 2 - getMeasuredWidth() / 2 + coverlength;
		float textProgress = coverTextLength / textWidth;
		if (coverlength <= indicator1) {
			mTextPaint.setShader(null);
			mTextPaint.setColor(mTextColor);
		} else if (indicator1 < coverlength && coverlength <= indicator2) {
			mProgressTextGradient = new LinearGradient((getMeasuredWidth() - textWidth) / 2, 0,
					(getMeasuredWidth() + textWidth) / 2, 0, new int[] { mTextCoverColor, mTextColor },
					new float[] { textProgress, textProgress + 0.001f }, Shader.TileMode.CLAMP);
			mTextPaint.setColor(mTextColor);
			mTextPaint.setShader(mProgressTextGradient);
		} else {
			mTextPaint.setShader(null);
			mTextPaint.setColor(mTextCoverColor);
		}
		canvas.drawText(text.toString(), (getMeasuredWidth() - textWidth) / 2, y, mTextPaint);
	}

	private void drawTextAbove(Canvas canvas) {
		final float y = canvas.getHeight() / 2 - (mTextPaint.descent() / 2 + mTextPaint.ascent() / 2);
		if (mCurrentText == null) {
			mCurrentText = "";
		}
		// color
		switch (mState) {
		case NONE:
			if (TextUtils.isEmpty(mCurrentText)) {
				mCurrentText = getResources().getString(R.string.download);
			}
			drawOnlyText(canvas, mCurrentText.toString(), mTextColor, y);
			break;
		case ERROR:
			if (TextUtils.isEmpty(mCurrentText)) {
				mCurrentText = getResources().getString(R.string.error);
			}
			drawOnlyText(canvas, mCurrentText.toString(), mTextColor, y);
			break;
		case DOWNLOADING:
			if (TextUtils.isEmpty(mCurrentText)) {
				mCurrentText = getResources().getString(R.string.downloading)
						+ getResources().getString(R.string.downloaded_divide,(int)mProgress);
			}
			drawProgressText(canvas, mCurrentText.toString(), mTextColor, mTextCoverColor, y);
			break;
		case PAUSE:
			if (TextUtils.isEmpty(mCurrentText)) {
				mCurrentText = getResources().getString(R.string.pause);
			}
			drawProgressText(canvas, mCurrentText.toString(), mTextColor, mTextCoverColor, y);
			break;
		case WAITING:
			if (TextUtils.isEmpty(mCurrentText)) {
				mCurrentText = getResources().getString(R.string.waiting);
			}
			drawDotText(canvas, mCurrentText.toString(), mTextColor, y);
			break;
		case FINISH:
			if (TextUtils.isEmpty(mCurrentText)) {
				mCurrentText = getResources().getString(R.string.finish);
			}
			drawOnlyText(canvas, mCurrentText.toString(), mTextColor, y);//TODO 不带点
			break;
		case OPEN:
			if (TextUtils.isEmpty(mCurrentText)) {
				mCurrentText = getResources().getString(R.string.open);
			}
			drawOnlyText(canvas, mCurrentText.toString(), mTextColor, y);
			break;
		}
		mCurrentText = null;
	}

	public int getState() {
		return mState;
	}

	// 定义下载状态常量
	/**
	 * 初始状态，需要下载
	 */
	public static final int NONE = 0; // 无状态 --> 等待
	/**
	 * 等待下载状态
	 */
	public static final int WAITING = 1; // 等待 --> 下载，暂停
	/**
	 * 正在下载状态，进度条在走动
	 */
	public static final int DOWNLOADING = 2; // 下载中 --> 暂停，完成，错误
	/**
	 * 暂停状态，有进度条
	 */
	public static final int PAUSE = 3; // 暂停 --> 等待，下载
	/**
	 * 下载完成，正在安装
	 */
	public static final int FINISH = 4; // 完成 --> 重新下载
	/**
	 * 错误状态
	 */
	public static final int ERROR = 5; // 错误 --> 等待
	/**
	 * 已安装，打开
	 */
	public static final int OPEN = 6; // 打开

	/**
	 * 设置下载状态
	 * 
	 * @param state
	 */
	public void setState(int state) {
		if (mState != state) {// 状态确实有改变
			this.mState = state;
			invalidate();
			//TODO  cxy  取消了 finish状态的动画
//			if (state == DownloadProgressButton.FINISH || state == DownloadProgressButton.WAITING) {
			if (state == DownloadProgressButton.WAITING) {
				// 开启两个点动画
				mDotAnimationSet.start();
			} else {
				mDotAnimationSet.cancel();
			}
		}
	}

	/**
	 * 设置按钮文字,设置文本仅限于NONE状态下
	 */
	public void setCurrentText(CharSequence charSequence) {
		if (mState == NONE) {
			mCurrentText = charSequence;
			invalidate();
		}
	}

	/**
	 * 设置带下载进度的文字,仅限于正在下载状态
	 */
	@TargetApi(Build.VERSION_CODES.KITKAT)
	public void setProgressText(String text, float progress) {
		//TODO cxy 状态为下载中和暂停都能显示进度
		if (mState == DOWNLOADING || mState == PAUSE) {
			if (progress >= mMinProgress && progress <= mMaxProgress) {
				if (!TextUtils.isEmpty(text)) {
					mCurrentText = text + getResources().getString(R.string.downloaded_divide, (int) progress);
				} else {
					mCurrentText = getResources().getString(R.string.downloading)
							+ getResources().getString(R.string.downloaded_divide, (int) progress);
				}
				mProgress = progress;
				mToProgress = progress;
				if (mProgressAnimation.isRunning()) {
					mProgressAnimation.resume();
					mProgressAnimation.start();
				} else {
					mProgressAnimation.start();
				}
			} else if (progress < mMinProgress) {
				mProgress = 0;
			} else if (progress > mMaxProgress) {
				mProgress = 100;
				mCurrentText = text + getResources().getString(R.string.downloaded_divide, (int) mProgress);
				invalidate();
			}
		}
	}

	public float getProgress() {
		return mProgress;
	}

	/**
	 * 更新进度
	 * 
	 * @param progress
	 */
	public void updateProgress(float progress) {
		setProgressText("", progress);
	}

	public float getButtonRadius() {
		return mButtonRadius;
	}

	public void setButtonRadius(float buttonRadius) {
		mButtonRadius = buttonRadius;
	}

	public int getTextColor() {
		return mTextColor;
	}

	@Override
	public void setTextColor(int textColor) {
		mTextColor = textColor;
	}

	public int getTextCoverColor() {
		return mTextCoverColor;
	}

	public void setTextCoverColor(int textCoverColor) {
		mTextCoverColor = textCoverColor;
	}

	public int getMinProgress() {
		return mMinProgress;
	}

	public void setMinProgress(int minProgress) {
		mMinProgress = minProgress;
	}

	public int getMaxProgress() {
		return mMaxProgress;
	}

	public void setMaxProgress(int maxProgress) {
		mMaxProgress = maxProgress;
	}

	@Override
	public void onRestoreInstanceState(Parcelable state) {
		SavedState ss = (SavedState) state;
		super.onRestoreInstanceState(ss.getSuperState());
		mState = ss.state;
		mProgress = ss.progress;
		mCurrentText = ss.currentText;
	}

	@Override
	public Parcelable onSaveInstanceState() {
		Parcelable superState = super.onSaveInstanceState();
		if (TextUtils.isEmpty(mCurrentText))
			switch (mState) {
			case NONE:
				mCurrentText = getResources().getString(R.string.download);
				break;
			case ERROR:
				mCurrentText = getResources().getString(R.string.error);
				break;
			case DOWNLOADING:
				mCurrentText = getResources().getString(R.string.downloading)
						+ getResources().getString(R.string.downloaded_divide, (int) mProgress);
				break;
			case PAUSE:
				mCurrentText = getResources().getString(R.string.pause);
				break;
			case WAITING:
				mCurrentText = getResources().getString(R.string.waiting);
				break;
			case FINISH:
				mCurrentText = getResources().getString(R.string.finish);
				break;
			case OPEN:
				mCurrentText = getResources().getString(R.string.open);
				break;
			}
		return new SavedState(superState, (int) mProgress, mState, mCurrentText.toString());
	}

	public static class SavedState extends BaseSavedState {

		private int progress;
		private int state;
		private String currentText;

		public SavedState(Parcelable parcel, int progress, int state, String currentText) {
			super(parcel);
			this.progress = progress;
			this.state = state;
			this.currentText = currentText;
		}

		private SavedState(Parcel in) {
			super(in);
			progress = in.readInt();
			state = in.readInt();
			currentText = in.readString();
		}

		@Override
		public void writeToParcel(Parcel out, int flags) {
			super.writeToParcel(out, flags);
			out.writeInt(progress);
			out.writeInt(state);
			out.writeString(currentText);
		}

		public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {

			@Override
			public SavedState createFromParcel(Parcel in) {
				return new SavedState(in);
			}

			@Override
			public SavedState[] newArray(int size) {
				return new SavedState[size];
			}
		};
	}

}
